package middleware

import (
	"Management/dao"
	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v4"
	"net/http"
	"time"
)

//Jwtkey 秘钥 可通过配置文件配置
var Jwtkey = []byte("DreamDew")

type MyClaims struct {
	DoDo string `json:"dodo"`//账号
	BiBi string `json:"bibi"`//密码
	jwt.StandardClaims
}

// CreateToken 生成token
func CreateToken(username string,password string) (string,error) {
	expireTime := time.Now().Add(60*time.Minute) //过期时间
	nowTime := time.Now() //当前时间
	claims := MyClaims{
		DoDo: username,
		BiBi: password,
		StandardClaims:jwt.StandardClaims{
			ExpiresAt:expireTime.Unix(), //过期时间戳
			IssuedAt: nowTime.Unix(), //当前时间戳
			Issuer: "DreamDew", //颁发者签名
			Subject: "vote", //签名主题
		},
	}
	tokenStruct := jwt.NewWithClaims(jwt.SigningMethodHS256,claims)
	return tokenStruct.SignedString(Jwtkey)
}

// CheckToken 验证token
func CheckToken(token string) (*MyClaims,bool) {
	tokenObj,_ := jwt.ParseWithClaims(token,&MyClaims{}, func(token *jwt.Token) (interface{}, error) {
		return Jwtkey,nil
	})
	if key,_ := tokenObj.Claims.(*MyClaims); tokenObj.Valid {
		return key,true
	}else{
		return key,false
	}

}

// JwtMiddleware jwt中间件
func JwtMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		//从请求头中获取token
		tokenStr := c.Request.Header.Get("giveaway")
		//用户不存在
		if tokenStr == "undefined"||tokenStr ==""  {
			c.JSON(http.StatusOK,gin.H{"code":0, "msg":"认证失败","err":"用户不存在或token为空"})
			c.Abort() //阻止执行
			return
		}

		tokenStruck,ok := CheckToken(tokenStr)

		//token超时
		if time.Now().Unix() > tokenStruck.ExpiresAt {
			c.JSON(http.StatusOK,gin.H{"code":0, "err":"token过期","msg":"过长时间未操作,请重新登录"})
			c.Abort() //阻止执行
			return
		}
		//验证token
		if !ok {
			c.JSON(http.StatusOK,gin.H{"code":0, "msg":"认证失败","err":"token不正确"})
			c.Abort() //阻止执行
			return
		}
		loginner:=dao.QueryLoginer(tokenStruck.DoDo)
		if loginner.ID==0{
			c.JSON(200,gin.H{"code":0,"err":"没有该用户","msg":"认证失败"})
			c.Abort() //阻止执行
			return
		}
		if loginner.Password!=tokenStruck.BiBi{
			c.JSON(200,gin.H{"code":0,"err":"用户信息出错","msg":"认证失败"})
			c.Abort() //阻止执行
			return
		}
		//更换token凭证
		if time.Now().Unix()+30*60*1000 >tokenStruck.IssuedAt{
			newtoken,_:=CreateToken(tokenStruck.DoDo,tokenStruck.BiBi)
			c.Header("newtoken", newtoken)
			//c.Request.Header.Set("token", newtoken)
		}
		c.Set("phone",tokenStruck.DoDo)
		c.Set("role",loginner.Role)
		c.Set("user_id",loginner.ID)
		c.Next()
	}
}